#include "common.h"

static int bExit = 0;

static int UdpBind(UdpUserType userType, unsigned short nPort, const unsigned int sendBufSize, const unsigned int recvBufSize);

int InitBlockInfoBuffer(BlockInfo *pBlockInfo, int nInfoSize, int nDataSize, unsigned char *pBuf, int nBufCount);

static int _PushBlockInfoData(BlockInfo *pBlockInfo, const unsigned char *pData, const int iSize, const unsigned char *pFrontData, const int iFrontSize);
static int clearBlockInfoData(BlockInfo *pBlockInfo);

struct recvData *CreateChain(int length)
{
	if (length < 1)
	{
		udi_erro_log("param error ! length = %d\n", length);
		return NULL;
	}

	int i;
	RecvData *all = NULL;
	all = (RecvData *)malloc(length * sizeof(RecvData));
	if (!all)
	{
		udi_erro_log("malloc fail !\n");
		return NULL;
	}
	for (i = 0; i < length - 1; i ++)
	{
		all[i].pNext = &all[i + 1];
	}
	all[length - 1].pNext = NULL;
	return &all[0];
}

void InsertHead(struct recvData **dst, struct recvData *src)
{
	struct recvData *temp = src;

	if (temp == NULL) return;

	while (temp->pNext != NULL) temp = temp->pNext;

	temp->pNext = *dst;
	*dst = src;
}


void InsertTail(struct recvData **dst, struct recvData *src)
{
	struct recvData *temp = *dst;

	if (temp == NULL)
	{
		*dst = src;
	}
	else
	{
		while (temp->pNext != NULL) temp = temp->pNext;
		temp->pNext = src;
	}
}

void InsertTailEx(RecvData **dst, RecvData *src, RecvData **dstLast)
{
	if (*dst == NULL)
	{
		*dst = src;
		*dstLast = src;
	}
	else
	{
		(*dstLast)->pNext = src;
		*dstLast = src;
	}
}

RecvData *GetHeadChain(RecvData **dst)
{
	RecvData *temp = *dst;

	if ((*dst) != NULL)
	{
		(*dst) = (*dst)->pNext;
		temp->pNext = NULL;
	}

	return temp;
}

void releaseChain(struct recvData **ppHead)
{
	if (!ppHead || !(*ppHead)) return;
}


int InitBlockInfoBuffer(BlockInfo *pBlockInfo, int nInfoSize, int nDataSize, unsigned char *pBuf, int nBufCount)
{
	if (sem_init(&(pBlockInfo->m_Semaphore), 0, 0) != 0)
	{
		printf("sem_init failure {%s(%d)}\n", __FILE__, __LINE__);
		return -1;
	}

	if (pthread_mutex_init(&pBlockInfo->m_Lock, NULL) != 0)
	{
		printf("pthread_mutex_init failure {%s(%d)}\n", __FILE__, __LINE__);
		return -2;
	}

	if (pBuf != NULL)
	{
		pBlockInfo->m_pInfo = (BufferInfo*)pBuf;

		if ((int)(nInfoSize * sizeof(BufferInfo) + nDataSize) > nBufCount)
		{
			printf("( nInfoSize*sizeof(BufferInfo)+nDataSize ) > nBufCount {%s(%d)}\n", __FILE__, __LINE__);
			return -3;
		}
	}
	else if ((pBlockInfo->m_pInfo = (BufferInfo*)malloc(nInfoSize * sizeof(BufferInfo) + nDataSize)) == NULL)
	{
		printf("sem_init failure {%s(%d)}\n", __FILE__, __LINE__);
		return -4;
	}
    memset(pBlockInfo->m_pInfo, 0, nInfoSize * sizeof(BufferInfo) + nDataSize);

	pBlockInfo->m_nInfoSize = nInfoSize;
	pBlockInfo->m_nDataSize = nDataSize;
	pBlockInfo->m_pData = (unsigned char *)(pBlockInfo->m_pInfo + pBlockInfo->m_nInfoSize);

	pBlockInfo->m_Push = pBlockInfo->m_Pop = pBlockInfo->m_pInfo;
	pBlockInfo->m_pCurr = pBlockInfo->m_pData;

	BufferInfo *pTempBufInfo = pBlockInfo->m_pInfo;

	for (int i = 0; i < pBlockInfo->m_nInfoSize; i++)
	{
		if (i == (pBlockInfo->m_nInfoSize - 1))
			pTempBufInfo->pNext = pBlockInfo->m_pInfo;
		else
			pTempBufInfo->pNext = pTempBufInfo + 1;

			pTempBufInfo++;
	}

	return 0;
}


int PushBlockInfoData(BlockInfo *pBlockInfo, const unsigned char *pData, const int iSize, const unsigned char *pFrontData, const int iFrontSize)
{
	int ret = _PushBlockInfoData(pBlockInfo, pData, iSize, pFrontData, iFrontSize);
	if(ret == -2 || ret == -3)
	{
		clearBlockInfoData(pBlockInfo);
		//return _PushBlockInfoData(pBlockInfo, pData, iSize, pFrontData, iFrontSize);
	}

	return ret;
}

static int _PushBlockInfoData(BlockInfo *pBlockInfo, const unsigned char *pData, const int iSize, const unsigned char *pFrontData, const int iFrontSize)
{
	int ret = 0;
	BufferInfo *Pop;

	pthread_mutex_lock(&(pBlockInfo->m_Lock));

	if (iSize + iFrontSize > pBlockInfo->m_nDataSize)
	{
		ret = -1;
		pthread_mutex_unlock(&(pBlockInfo->m_Lock));
		return ret;
	}

	if (pBlockInfo->m_Push->nFlag != 0)
	{
		ret = -2;
		pthread_mutex_unlock(&(pBlockInfo->m_Lock));
		return ret;
	}

	if (iSize + iFrontSize > (pBlockInfo->m_pData + pBlockInfo->m_nDataSize - pBlockInfo->m_pCurr))
	{
		pBlockInfo->m_pCurr = pBlockInfo->m_pData;
	}

	Pop = pBlockInfo->m_Pop;

	while (Pop->nFlag)
	{
		if (Pop->pData >= pBlockInfo->m_pCurr)
		{
			if ((Pop->pData - pBlockInfo->m_pCurr) < iSize + iFrontSize)
			{
				ret = -3;
				udi_erro_log("push fail -3 ! %d < %d + %d\n", (int)(Pop->pData - pBlockInfo->m_pCurr), iSize, iFrontSize);
				pthread_mutex_unlock(&(pBlockInfo->m_Lock));
				return ret;
			}
		}
		Pop = Pop->pNext;
	}

	if (pFrontData && iFrontSize > 0)
	{
		memcpy(pBlockInfo->m_pCurr, pFrontData, iFrontSize);
	}

	if (pData && iSize > 0)
	{
		memcpy(pBlockInfo->m_pCurr + iFrontSize, pData, iSize);
	}

	pBlockInfo->m_Push->pData = pBlockInfo->m_pCurr;
	pBlockInfo->m_Push->nSize = iSize + iFrontSize;
	pBlockInfo->m_Push->nFlag = 1;
	pBlockInfo->m_Push = pBlockInfo->m_Push->pNext;

	pBlockInfo->m_pCurr += (iSize + iFrontSize);

	sem_post(&(pBlockInfo->m_Semaphore));

	pthread_mutex_unlock(&(pBlockInfo->m_Lock));

	return ret;
}

static int clearBlockInfoData(BlockInfo *pBlockInfo)
{
	return 0;

	pthread_mutex_lock(&pBlockInfo->m_Lock);

	pBlockInfo->m_pCurr = pBlockInfo->m_pData;
	pBlockInfo->m_Push = pBlockInfo->m_pInfo;
	pBlockInfo->m_Pop = pBlockInfo->m_pInfo;

	BufferInfo *tmp;
	int packageNum = 0;
	for(tmp = pBlockInfo->m_pInfo; tmp; tmp = tmp->pNext)
	{
		if(tmp->nFlag)
		{
			packageNum ++;
			tmp->nFlag = 0;
		}
	}

	pthread_mutex_unlock(&pBlockInfo->m_Lock);
	udi_erro_log("queue data too much ! clear all ! totally %d packages !\n", packageNum);
	return packageNum;
}

int PopBlockInfoData(BlockInfo *pBlockInfo, void(*pFunc)(const unsigned char*, const int, void*), void* arg)
{
	if (pBlockInfo == NULL || pBlockInfo->m_Pop == NULL)
	{
		printf("%s: para error ! pBlockInfo=%p\n", __FUNCTION__, pBlockInfo);
		return -1;
	}

	while (pBlockInfo && pBlockInfo->m_Pop && pBlockInfo->m_Pop->nFlag)
	{
		pFunc(pBlockInfo->m_Pop->pData, pBlockInfo->m_Pop->nSize, arg);
		pthread_mutex_lock(&(pBlockInfo->m_Lock));
		pBlockInfo->m_Pop->nFlag = 0;
		pBlockInfo->m_Pop = pBlockInfo->m_Pop->pNext;
		pthread_mutex_unlock(&(pBlockInfo->m_Lock));
	}

	return 0;
}

int PopBlockInfoDataNotConst(BlockInfo *pBlockInfo, void(*pFunc)(unsigned char*, const int, void*), void* arg)
{
	if (pBlockInfo == NULL || pBlockInfo->m_Pop == NULL)
	{
		printf("%s: para error ! pBlockInfo=%p\n", __FUNCTION__, pBlockInfo);
		return -1;
	}

	while (pBlockInfo && pBlockInfo->m_Pop && pBlockInfo->m_Pop->nFlag)
	{
		pFunc(pBlockInfo->m_Pop->pData, pBlockInfo->m_Pop->nSize, arg);
		pthread_mutex_lock(&(pBlockInfo->m_Lock));
		pBlockInfo->m_Pop->nFlag = 0;
		pBlockInfo->m_Pop = pBlockInfo->m_Pop->pNext;
		pthread_mutex_unlock(&(pBlockInfo->m_Lock));
	}

	return 0;
}

int PopBlockInfoDataEx(BlockInfo *pBlockInfo, void(*pFunc)(const unsigned char*, const int, void*), void* arg, int(*loopConditionFunc)(void), int timeOut)
{
	struct timespec ts;
	struct timeval  tv;
	while (loopConditionFunc())
	{
		gettimeofday(&tv, NULL);
		ts.tv_sec = tv.tv_sec + timeOut;
		ts.tv_nsec = tv.tv_usec * 1000;
		sem_timedwait(&(pBlockInfo->m_Semaphore), &ts);

		PopBlockInfoData(pBlockInfo, pFunc, arg);
	}

	return 0;
}

int PopBlockInfoDataExNotConst(BlockInfo *pBlockInfo, void(*pFunc)(unsigned char*, const int, void*), void* arg, int(*loopConditionFunc)(void *arg), int timeOut)
{
	struct timespec ts;
	struct timeval  tv;
	while (loopConditionFunc(arg))
	{
		gettimeofday(&tv, NULL);
		ts.tv_sec = tv.tv_sec + timeOut;
		ts.tv_nsec = tv.tv_usec * 1000;
		sem_timedwait(&(pBlockInfo->m_Semaphore), &ts);

		PopBlockInfoDataNotConst(pBlockInfo, pFunc, arg);
	}

	return 0;
}

int PopBlockInfoDataExNotConst2(BlockInfo *pBlockInfo, void(*pFunc)(unsigned char*, const int, void*), void* arg, int *loopCondition, int timeOut)
{
	struct timespec ts;
	struct timeval  tv;
	while (*loopCondition)
	{
		gettimeofday(&tv, NULL);
		ts.tv_sec = tv.tv_sec + timeOut;
		ts.tv_nsec = tv.tv_usec * 1000;
		sem_timedwait(&(pBlockInfo->m_Semaphore), &ts);

		PopBlockInfoDataNotConst(pBlockInfo, pFunc, arg);
	}

	return 0;
}

int initVideoPreviewBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, udpVideoBlockBufMaxNumber, udpVideoPreviewBlockSize, NULL, 0);
}
int initVideoBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, udpVideoBlockBufMaxNumber, udpVideoBlockSize, NULL, 0);
}
int initVideoMainBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, udpVideoBlockBufMaxNumber, udpVideoMainBlockSize, NULL, 0);
}
int initVideoServerBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, udpVideoBlockBufMaxNumber, udpVideoServerBlockSize, NULL, 0);
}
int initVideoServerMainBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, udpVideoBlockBufMaxNumber, udpVideoServerMainBlockSize, NULL, 0);
}
int initAudioBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, udpAudioBlockBufMaxNumber, udpAudioBlockSize, NULL, 0);
}
int initVideoAudioBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, tcpVideoAudioBufMaxNumber, tcpVideoAudioBlockSize, NULL, 0);
}
int initVideoAudioMainBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, tcpVideoAudioBufMaxNumber, tcpVideoAudioMainBlockSize, NULL, 0);
}
int pushBlock(BlockInfo *pBlockInfo, unsigned char *pData, int iSize)
{
	return PushBlockInfoData(pBlockInfo, pData, iSize, NULL, 0);
}
int pushBlockEx(BlockInfo *pBlockInfo, const unsigned char *pData, const int iSize, const unsigned char type)
{
	return PushBlockInfoData(pBlockInfo, pData, iSize, &type, 1);
}
int pushBlo(BlockInfo *pBlockInfo, const unsigned char *pData, const int iSize, const unsigned char *pf, const int ifSize)
{
	return PushBlockInfoData(pBlockInfo, pData, iSize, pf, ifSize);
}

int initClientSendVideoBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, udpVideoClientSendBlockBufMaxNumber, udpVideoClientSendBlockSize, NULL, 0);
}
int initClientSendBigVideoBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, udpVideoClientSendBlockBufMaxNumber, udpVideoClientSendBigBlockSize, NULL, 0);
}
int initClientSendAudioBlock(BlockInfo *pBlockInfo)
{
	return InitBlockInfoBuffer(pBlockInfo, udpAudioClientSendBlockBufMaxNumber, udpAudioClientSendBlockSize, NULL, 0);
}

void releaseBlock(BlockInfo *pBlockInfo)
{
	if (pBlockInfo)
	{
		sem_destroy(&(pBlockInfo->m_Semaphore));

		//pthread_mutexattr_t mattr;
		//if (pthread_mutexattr_init(&mattr) != 0)
		//	printf("pthread_mutexattr_init failure {%s(%d)}\n", __FILE__, __LINE__);
		//if (pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED) != 0)
		//	printf("pthread_mutexattr_init failure {%s(%d)}\n", __FILE__, __LINE__);
		//pthread_mutexattr_destroy(&mattr);
        pthread_mutex_destroy(&pBlockInfo->m_Lock);
	}

	if (pBlockInfo->m_pInfo)
	{
		free(pBlockInfo->m_pInfo);
		pBlockInfo->m_pInfo = NULL;
	}
}


static int UdpBind(UdpUserType userType, unsigned short nPort, const unsigned int sendBufSize, const unsigned int recvBufSize)
{
	//char    temp[80];
	int 		 iSocket;
	int       	flag = 1;
	int			len = sizeof(int);
	socklen_t svrlen;
	struct sockaddr_in localaddr;

	if ((iSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
	{
		udi_erro_log("create socket fail ! nPort = %u\n", (unsigned int)nPort);
		return -1;
	}

	int optLen = sizeof(int);
	int rcvSize;

	getsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, (void *)&rcvSize, (socklen_t *)&optLen);
	//udi_erro_log("before:sock recv buf size = %u\n", rcvSize);
	getsockopt(iSocket, SOL_SOCKET, SO_SNDBUF, (void *)&rcvSize, (socklen_t *)&optLen);
	//udi_erro_log("before:sock send buf size = %u\n", rcvSize);

	if (userType == eUdpServer)
	{
		setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&flag, len);

		rcvSize = sendBufSize / 2;
		setsockopt(iSocket, SOL_SOCKET, SO_SNDBUF, (const char *)&rcvSize, optLen);

		getsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, (void *)&rcvSize, (socklen_t *)&optLen);
		//udi_erro_log("mid:sock recv buf size = %u\n", rcvSize);
		getsockopt(iSocket, SOL_SOCKET, SO_SNDBUF, (void *)&rcvSize, (socklen_t *)&optLen);
		//udi_erro_log("mid:sock send buf size = %u\n", rcvSize);

		rcvSize = recvBufSize / 2;
		setsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvSize, optLen);

		getsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, (void *)&rcvSize, (socklen_t *)&optLen);
		//udi_erro_log("after:sock recv buf size = %u\n", rcvSize);
		getsockopt(iSocket, SOL_SOCKET, SO_SNDBUF, (void *)&rcvSize, (socklen_t *)&optLen);
		//udi_erro_log("after:sock send buf size = %u\n", rcvSize);
		
	}
	else if(userType == eUdpClient)
	{
		//setsockopt(iSocket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char *)&flag, len);

		rcvSize = sendBufSize / 2;
		setsockopt(iSocket, SOL_SOCKET, SO_SNDBUF, (const char *)&rcvSize, optLen);

		getsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, (void *)&rcvSize, (socklen_t *)&optLen);
		//udi_erro_log("mid:sock recv buf size = %u\n", rcvSize);
		getsockopt(iSocket, SOL_SOCKET, SO_SNDBUF, (void *)&rcvSize, (socklen_t *)&optLen);
		//udi_erro_log("mid:sock send buf size = %u\n", rcvSize);

		rcvSize = recvBufSize / 2;
		setsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, (const char *)&rcvSize, optLen);

		getsockopt(iSocket, SOL_SOCKET, SO_RCVBUF, (void *)&rcvSize, (socklen_t *)&optLen);
		//udi_erro_log("after:sock recv buf size = %u\n", rcvSize);
		getsockopt(iSocket, SOL_SOCKET, SO_SNDBUF, (void *)&rcvSize, (socklen_t *)&optLen);
		//udi_erro_log("after:sock send buf size = %u\n", rcvSize);
	}

	flag = fcntl(iSocket, F_GETFL, 0);
	flag |= O_NONBLOCK;
	if (fcntl(iSocket, F_SETFL, flag) == -1)
	{
		udi_erro_log("set socket nonblock fail !\n");
		close(iSocket);
		return -3;
	}

	svrlen = sizeof(localaddr);
	memset((char *)&localaddr, 0x0, svrlen);

	localaddr.sin_family = AF_INET;
	localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	localaddr.sin_port = htons(nPort);

	if (bind(iSocket, (struct sockaddr *)&localaddr, svrlen) < 0)
	{
		close(iSocket);
		return -2;
	}

	return iSocket;
}

int udpServerBind(unsigned short port)
{
	return UdpBind(eUdpServer, port, udpServerSysSockSendBufSize, udpServerSysSockRecvBufSize);
}
int udpClientBind(unsigned short port)
{
	return UdpBind(eUdpClient, port, udpClientSysSockSendBufSize, udpClientSysSockRecvBufSize);
}
int udpClientBindEx(const unsigned short port, const unsigned int sendBufSize, const unsigned int recvBufSize)
{
	return UdpBind(eUdpClient, port, sendBufSize, recvBufSize);
}


int IsExit()
{
	return bExit;
}
void setIsExit(int value)
{
	bExit = value;
}
int IsLoop()
{
	return !IsExit();
}

static int create_thread(pthread_t *pid, void*(*thread_callback)(void*), void *arg, const size_t stack_size)
{
    if (!pid || stack_size < 4 * 1024)
    {
        udi_erro_log("%s: para errror ! %p,%p,%d\n", __FUNCTION__, pid, thread_callback, (int)stack_size);
        return -1;
    }

    size_t stacksize;
    pthread_attr_t attr, *set_attr;

#if __PURE_LINUX__
    if (pthread_attr_init(&attr) != 0) udi_erro_log("pthread_attr_init failure !\n");
    if (pthread_attr_getstacksize(&attr, &stacksize) != 0) udi_erro_log("pthread_attr_getstacksize failure !\n");
    if (pthread_attr_setstacksize(&attr, stack_size) != 0) udi_erro_log("pthread_attr_setstacksize failure !\n");
    if (pthread_attr_getstacksize(&attr, &stacksize) != 0) udi_erro_log("pthread_attr_getstacksize failure !\n");
    set_attr = &attr;
#else
    set_attr = NULL;
#endif

    return pthread_create(pid, set_attr, thread_callback, arg);
}

static int create_thread(pthread_t *pid, void*(*thread_callback)(void*), void *arg, const size_t stack_size);

int create_thread_small(pthread_t *pid, void*(*thread_callback)(void*), void *arg)
{
    return create_thread(pid, thread_callback, arg, MIN_THREAD_STACK_SIZE);
}

int create_thread_middle(pthread_t *pid, void*(*thread_callback)(void*), void *arg)
{
    return create_thread(pid, thread_callback, arg, MIDDLE_THREAD_STACK_SIZE);
}

int create_thread_normal(pthread_t *pid, void*(*thread_callback)(void*), void *arg)
{
    return create_thread(pid, thread_callback, arg, NORMAL_THREAD_STACK_SIZE);
}

void printf_ex(const char *name, const unsigned char *data, const int data_size)
{
    int i = 0;
    int count = 0;
    char temp[512] = { 0 };
    printf("%u:%s=%d,", (unsigned int)pthread_self(), name, data_size);
    count = sprintf(temp, "%u:%s=%d,", (unsigned int)pthread_self(), name, data_size);
    for (i = 0; i < data_size; i++)
    {
        count += sprintf(temp + count, "%x ", data[i]);
        printf("%x ", data[i]);
    }
    printf("\n");
    udi_info_log("%s\n", temp);
}

int getIpNumFromRtspUrl(const char *url)
{
    if(!url)
    {
        udi_erro_log("url is NULL !\n");
        return 0;
    }

    char startSign[] = "rtsp://";
    char stopSign1[] = ":";
    char stopSign2[] = "/";
    char tmpResult[256];
    int size;
    strcpy(tmpResult, url);
    char *start = strstr(tmpResult, startSign);
    if(!start)
    {
        udi_erro_log("not found %s\n", startSign);
        return 0;
    }

    start += strlen(startSign);
    char *stop = strstr(start, stopSign1);
    if(stop)
    {
        size = stop - start;
        stop[0] = '\0';
    }
    else
    {
        stop = strstr(start, stopSign2);
        if(!stop)
        {
            udi_erro_log("not found %s or %s\n", stopSign1, stopSign2);
            return 0;
        }
        size = stop - start;
        stop[0] = '\0';
    }

    int ipnum = inet_addr(start);
    udi_info_log("######## pause ip from rtsp %s is %s, ipnum is %d\n", url, start, ipnum);
    return ipnum;
}

FILE* openFileRB(const char *name)
{
    FILE *fp = NULL;
    if (name)
    {
        fp = fopen(name, "rb");
    }

    return fp;
}

FILE* openFileWR(const char *name)
{
    FILE *fp = NULL;
    if (name)
    {
        fp = fopen(name, "wb");
    }

    return fp;
}

unsigned int GetTickCount()
{
	struct timespec ts;

	clock_gettime(CLOCK_MONOTONIC, &ts);

	return (unsigned int)(ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
}

int getAudioSampleRate(const unsigned char *audioData)
{
	if(!audioData)
	{
		return -1;
	}

	const unsigned int g_aacSampleRateFrequency[] = { 96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,8000,8000,8000,8000,8000,8000 };
	unsigned char sampleRateIdx = (audioData[2] >> 2) & 0x0F;
	int sampleRate =  g_aacSampleRateFrequency[sampleRateIdx];
	return sampleRate;
}

